//package top.lixunda.commerce.common.core.config;
//
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.context.annotation.Primary;
//import org.springframework.session.web.http.CookieSerializer;
//import org.springframework.stereotype.Component;
//
//import javax.servlet.http.Cookie;
//import javax.servlet.http.HttpServletRequest;
//import javax.servlet.http.HttpServletResponse;
//import java.time.Instant;
//import java.time.OffsetDateTime;
//import java.time.ZoneOffset;
//import java.time.format.DateTimeFormatter;
//import java.util.ArrayList;
//import java.util.Base64;
//import java.util.BitSet;
//import java.util.List;
//import java.util.regex.Matcher;
//import java.util.regex.Pattern;
//
///**
// * 自定义Session序列化器
// *
// * @author lixunda
// * @version time:2020/5/3 3:23
// */
//@Slf4j
//@Primary
//@Component
//public class SpringSessionCookieSerializer implements CookieSerializer {
//
//    static final String SET_COOKIE = "Set-Cookie";
//
//    static final String COOKIE = "Cookie";
//
//    private static final BitSet DOMAIN_VALID = new BitSet(128);
//    private String cookieName = "SESSION";
//    private Boolean useSecureCookie = null;
//    private boolean useHttpOnlyCookie = true;
//    private String cookiePath = null;
//    private Integer cookieMaxAge = null;
//    private String domainName = null;
//    private Pattern domainNamePattern = null;
//    private String jvmRoute = null;
//    private boolean useBase64Encoding = true;
//    private String rememberMeRequestAttribute = null;
//    private String sameSite = "Lax";
//
//    public SpringSessionCookieSerializer() {
//        log.info("SpringSession 自定义序列化器");
//        this.setSameSite(null);
//    }
//
//    @Override
//    public List<String> readCookieValues(HttpServletRequest request) {
//        List<String> matchingCookieValues = new ArrayList<>();
//        String cookieValue = (String) request.getAttribute(SET_COOKIE);
//        if (cookieValue != null && cookieValue.length() > 0) {
//            // cookieValue 中保存的数据是cookie，而不是session，获取其中的session
//            String[] strings = cookieValue.split(";");
//            for (String temp : strings) {
//                temp = temp.trim();
//                if (temp.length() > 0 && temp.startsWith(cookieName + "=")) {
//                    cookieValue = temp.replace(cookieName + "=", "");
//                    break;
//                }
//            }
//            String sessionId = this.useBase64Encoding ? this.base64Decode(cookieValue) : cookieValue;
//            if (sessionId != null) {
//                if (this.jvmRoute != null && sessionId.endsWith(this.jvmRoute)) {
//                    sessionId = sessionId.substring(0, sessionId.length() - this.jvmRoute.length());
//                }
//
//                matchingCookieValues.add(sessionId);
//            }
//            return matchingCookieValues;
//        }
//
//        Cookie[] cookies = request.getCookies();
//        if (cookies != null) {
//            Cookie[] var4 = cookies;
//            int var5 = cookies.length;
//
//            for (int var6 = 0; var6 < var5; ++var6) {
//                Cookie cookie = var4[var6];
//                cookieValue = cookie.getValue();
//                if (this.cookieName.equals(cookie.getName())) {
//                    String sessionId = this.useBase64Encoding ? this.base64Decode(cookieValue) : cookieValue;
//                    if (sessionId != null) {
//                        if (this.jvmRoute != null && sessionId.endsWith(this.jvmRoute)) {
//                            sessionId = sessionId.substring(0, sessionId.length() - this.jvmRoute.length());
//                        }
//
//                        matchingCookieValues.add(sessionId);
//                    }
//                }
//            }
//        }
//
//        return matchingCookieValues;
//    }
//
//    @Override
//    public void writeCookieValue(CookieValue cookieValue) {
//        HttpServletRequest request = cookieValue.getRequest();
//        HttpServletResponse response = cookieValue.getResponse();
//
//        String temp = (String) request.getAttribute(SET_COOKIE);
//        if (temp != null && temp.length() > 0) {
//            return;
//        }
//
//        StringBuilder sb = new StringBuilder();
//        sb.append(this.cookieName).append('=');
//        String value = this.getValue(cookieValue);
//        if (value != null && value.length() > 0) {
//            this.validateValue(value);
//            sb.append(value);
//        }
//
//        int maxAge = this.getMaxAge(cookieValue);
//        if (maxAge > -1) {
//            sb.append("; Max-Age=").append(cookieValue.getCookieMaxAge());
//            OffsetDateTime expires = maxAge != 0 ? OffsetDateTime.now().plusSeconds((long) maxAge) : Instant.EPOCH.atOffset(ZoneOffset.UTC);
//            sb.append("; Expires=").append(expires.format(DateTimeFormatter.RFC_1123_DATE_TIME));
//        }
//
//        String domain = this.getDomainName(request);
//        if (domain != null && domain.length() > 0) {
//            this.validateDomain(domain);
//            sb.append("; Domain=").append(domain);
//        }
//
//        String path = this.getCookiePath(request);
//        if (path != null && path.length() > 0) {
//            this.validatePath(path);
//            sb.append("; Path=").append(path);
//        }
//
//        if (this.isSecureCookie(request)) {
//            sb.append("; Secure");
//        }
//
//        if (this.useHttpOnlyCookie) {
//            sb.append("; HttpOnly");
//        }
//
//        if (this.sameSite != null) {
//            sb.append("; SameSite=").append(this.sameSite);
//        }
//
//        String cookie = sb.toString();
//        response.addHeader(SET_COOKIE, cookie);
//        request.setAttribute(SET_COOKIE, cookie);
//    }
//
//    private String base64Decode(String base64Value) {
//        try {
//            byte[] decodedCookieBytes = Base64.getDecoder().decode(base64Value);
//            return new String(decodedCookieBytes);
//        } catch (Exception var3) {
//            log.debug("Unable to Base64 decode value: " + base64Value);
//            return null;
//        }
//    }
//
//    private String base64Encode(String value) {
//        byte[] encodedCookieBytes = Base64.getEncoder().encode(value.getBytes());
//        return new String(encodedCookieBytes);
//    }
//
//    private String getValue(CookieValue cookieValue) {
//        String requestedCookieValue = cookieValue.getCookieValue();
//        String actualCookieValue = requestedCookieValue;
//        if (this.jvmRoute != null) {
//            actualCookieValue = requestedCookieValue + this.jvmRoute;
//        }
//
//        if (this.useBase64Encoding) {
//            actualCookieValue = this.base64Encode(actualCookieValue);
//        }
//
//        return actualCookieValue;
//    }
//
//    private void validateValue(String value) {
//        int start = 0;
//        int end = value.length();
//        if (end > 1 && value.charAt(0) == '"' && value.charAt(end - 1) == '"') {
//            start = 1;
//            --end;
//        }
//
//        char[] chars = value.toCharArray();
//
//        for (int i = start; i < end; ++i) {
//            char c = chars[i];
//            if (c < '!' || c == '"' || c == ',' || c == ';' || c == '\\' || c == 127) {
//                throw new IllegalArgumentException("Invalid character in cookie value: " + Integer.toString(c));
//            }
//        }
//
//    }
//
//    private int getMaxAge(CookieValue cookieValue) {
//        int maxAge = cookieValue.getCookieMaxAge();
//        if (maxAge < 0) {
//            if (this.rememberMeRequestAttribute != null && cookieValue.getRequest().getAttribute(this.rememberMeRequestAttribute) != null) {
//                cookieValue.setCookieMaxAge(2147483647);
//            } else if (this.cookieMaxAge != null) {
//                cookieValue.setCookieMaxAge(this.cookieMaxAge);
//            }
//        }
//
//        return cookieValue.getCookieMaxAge();
//    }
//
//    private void validateDomain(String domain) {
//        int i = 0;
//        int cur = -1;
//
//        for (char[] chars = domain.toCharArray(); i < chars.length; ++i) {
//            int prev = cur;
//            cur = chars[i];
//            if (!DOMAIN_VALID.get(cur) || (prev == 46 || prev == -1) && (cur == 46 || cur == 45) || prev == 45 && cur == 46) {
//                throw new IllegalArgumentException("Invalid cookie domain: " + domain);
//            }
//        }
//
//        if (cur == 46 || cur == 45) {
//            throw new IllegalArgumentException("Invalid cookie domain: " + domain);
//        }
//    }
//
//    private void validatePath(String path) {
//        char[] var2 = path.toCharArray();
//        int var3 = var2.length;
//
//        for (int var4 = 0; var4 < var3; ++var4) {
//            char ch = var2[var4];
//            if (ch < ' ' || ch > '~' || ch == ';') {
//                throw new IllegalArgumentException("Invalid cookie path: " + path);
//            }
//        }
//
//    }
//
//    private boolean isSecureCookie(HttpServletRequest request) {
//        return this.useSecureCookie == null ? request.isSecure() : this.useSecureCookie;
//    }
//
//    public void setSameSite(String sameSite) {
//        this.sameSite = sameSite;
//    }
//
//    private String getDomainName(HttpServletRequest request) {
//        if (this.domainName != null) {
//            return this.domainName;
//        } else {
//            if (this.domainNamePattern != null) {
//                Matcher matcher = this.domainNamePattern.matcher(request.getServerName());
//                if (matcher.matches()) {
//                    return matcher.group(1);
//                }
//            }
//
//            return null;
//        }
//    }
//
//    private String getCookiePath(HttpServletRequest request) {
//        return this.cookiePath == null ? request.getContextPath() + "/" : this.cookiePath;
//    }
//
//    static {
//        char c;
//        for (c = '0'; c <= '9'; ++c) {
//            DOMAIN_VALID.set(c);
//        }
//
//        for (c = 'a'; c <= 'z'; ++c) {
//            DOMAIN_VALID.set(c);
//        }
//
//        for (c = 'A'; c <= 'Z'; ++c) {
//            DOMAIN_VALID.set(c);
//        }
//
//        DOMAIN_VALID.set(46);
//        DOMAIN_VALID.set(45);
//    }
//
//}
